import React from "react";
// import axios from "axios";
import {BASE_URL} from '../../utils/url'
import {API} from '../../utils/api'
import { Link } from "react-router-dom";
import { Toast } from "antd-mobile";
// import './index.css'
import styles from "./index.module.css";

import NavHeader from "../../components/NavHeader";
import HouseItem from "../../components/HouseItem"

// console.log(window);
// 解决脚手架中全局变量访问的问题
const BMap = window.BMap;
// 覆盖物样式
const labelStyle = {
  cursor: "pointer",
  border: "0px solid rgb(255, 0, 0)",
  padding: "0px",
  whiteSpace: "nowrap",
  fontSize: "12px",
  color: "rgb(255, 255, 255)",
  textAlign: "center",
};

export default class Map extends React.Component {
  state = {
    housesList: [],
    isShowList: false,
  };

  // 在钩子函数中调用 百度地图实例对象
  componentDidMount() {
    this.initMap();
  }
  initMap() {
    // 获取当前定位城市
    const { label, value } = JSON.parse(localStorage.getItem("hkzf_city"));
    // console.log(label, value);

    // 初始化地图实例
    const map = new BMap.Map("container");
    // 作用：能够在其他方法中通过 this 来获取到地图对象
    this.map = map;
    // 创建地址解析器实例
    const myGeo = new BMap.Geocoder();
    // 将地址解析结果显示在地图上，并调整地图视野
    myGeo.getPoint(
      label,
      async (point) => {
        if (point) {
          //  初始化地图 设置中心点坐标和地图级别
          map.centerAndZoom(point, 11);
          map.enableScrollWheelZoom(); //开启鼠标滚轮缩放
          // 添加地图缩放控件 和 地图比例尺控件
          map.addControl(new BMap.NavigationControl());
          map.addControl(new BMap.ScaleControl());
          // // 对以下代码进行封装
          // // 获取区域房源数据
          // const {
          //   data: { body },
          // } = await axios.get(`http://localhost:8080/area/map?id=${value}`);
          // console.log(body);
          // // 遍历房源信息，创建对应的覆盖物
          // body.map((item) => {
          //   const {
          //     coord: { longitude, latitude },
          //     label: areaName,
          //     count,
          //     value,
          //   } = item;
          //   const opts = {
          //     position: new BMap.Point(longitude, latitude),
          //     offset: new BMap.Size(-35, -35),
          //   };

          //   // 说明：设置 setContent 后，第一个参数中设置的文本内容就失效了，因此，直接清空即可
          //   const label = new BMap.Label("", opts);

          //   // 设置房源覆盖物内容
          //   label.setContent(`
          //       <div class="${styles.bubble}">
          //         <p class="${styles.name}">${areaName}</p>
          //         <p>${count}套</p>
          //       </div>
          //     `);

          //   // 设置样式
          //   label.setStyle(labelStyle);
          //   // 给label添加唯一标识 用于获取下级数据传值
          //   label.id = value;
          //   // 添加单击事件
          //   label.addEventListener("click", () => {
          //     console.log("房源覆盖物被点击了", value);
          //     // 当点击了覆盖物，要以当前点击的覆盖物为中心来放大地图
          //     map.centerAndZoom(this.position, 13);
          //     // 解决清除覆盖物的时候，百度地图js报错问题
          //     setTimeout(function () {
          //       map.clearOverlays();
          //     }, 0);

          //       // 获取区域房源数据
          //     // axios.get(`http://localhost:8080/area/map?id=${value}`).then(result => console.log(result))
          //     // axios.get(`http://localhost:8080/area/map?id=${value}`) // 百度地图API不支持通过 async-await 的方式处理异步请求

          //   });

          //   // 添加覆盖物到地图中
          //   map.addOverlay(label);
          //   return true;
          // });

          this.renderOverlays(value);
        }
      },
      label
    );
    // 监听 movestart 地图移动事件 移动地图时 房屋信息列表消失(控制样式 .show 的显示与隐藏来达到 动画效果是通过CSS的 translate 来实现的)
    map.addEventListener("movestart", () => {
      if (this.state.isShowList) {
        this.setState({
          isShowList: false,
        });
      }
    });
  }
  // 封装 renderOverlays() 方法渲染覆盖物
  async renderOverlays(id) {
    try {
      //  设置loading效果
      Toast.loading("数据加载中", 0, null, false);
      // 接收区域id参数，获取该区域下的房源数据
      // 获取区域房源数据
      const res = await API.get(`/area/map?id=${id}`);
      //  关闭loading效果
      Toast.hide();
      //  console.log(res);
      // 获取覆盖物类型以及下级地图缩放级别 这里额外封装一个获取覆盖物类型和缩放级别的方法
      let { type, nextZoom } = this.getTypeAndZoom();
      //  创建覆盖物
      this.createOverlays(res.data.body, type, nextZoom);
    } catch (error) {
      console.log(error);
      //  关闭loading效果
      Toast.hide();
    }
  }

  // 计算要绘制的覆盖物类型和下一个缩放级别
  // 区   -> 11 ，范围：>=10 <12
  // 镇   -> 13 ，范围：>=12 <14
  // 小区 -> 15 ，范围：>=14 <16
  getTypeAndZoom() {
    // 获取当前地图缩放级别
    let zoom = this.map.getZoom();
    let nextZoom, type;
    // console.log('当前地图缩放级别：', zoom)
    if (zoom >= 10 && zoom < 12) {
      // 为什么不直接等于11 缩放倍数可能是小数吗
      nextZoom = 13;
      // circle 表示绘制圆形的覆盖物，区
      type = "circle";
    } else if (zoom >= 12 && zoom < 14) {
      nextZoom = 15;
      // circle 表示绘制圆形的覆盖物，镇
      type = "circle";
    } else if (zoom >= 14 && zoom < 16) {
      // circle 表示绘制矩形的覆盖物，小区
      type = "rect";
    }
    return { nextZoom, type };
  }

  //  createOverlays() 方法 创建覆盖物
  createOverlays(data, type, zoom) {
    //  根据传入的类型，调用对应方法，创建覆盖物，需要判断是创建区镇的覆盖物还是小区覆盖物
    // 遍历房源信息，创建对应的覆盖物
    data.forEach((item) => {
      const {
        coord: { longitude, latitude },
        label: areaName,
        count,
        value,
      } = item;
      const opts = {
        position: new BMap.Point(longitude, latitude),
        offset: new BMap.Size(-35, -35),
      };
      const point = opts.position;
      // 判断需要渲染的是哪种类型
      if (type === "circle") {
        // 区 或者 镇
        this.createCircle(point, areaName, count, value, zoom);
      } else if (type === "rect") {
        // 小区
        this.createRect(point, areaName, count, value);
      }
    });
  }
  //  createCircle() 方法 创建镇级区域覆盖物
  createCircle(point, name, count, value, zoom) {
    //  根据传入的数据创建覆盖物，绑定事件（放大地图，清除覆盖物，渲染下一级房源数据）
    // 说明：设置 setContent 后，第一个参数中设置的文本内容就失效了，因此，直接清空即可
    const label = new BMap.Label("", {
      position: point,
      offset: new BMap.Size(-35, -35),
    });

    // 设置房源覆盖物内容
    label.setContent(`
        <div class="${styles.bubble}">
          <p class="${styles.name}">${name}</p>
          <p>${count}套</p>
        </div>
      `);

    // 设置样式
    label.setStyle(labelStyle);
    // 给label添加唯一标识 用于获取下级数据传值
    label.id = value;
    // 添加单击事件
    label.addEventListener("click", () => {
      // console.log("房源覆盖物被点击了", value);
      // 调用 renderOverlays 方法，获取该区域下的房源数据
      this.renderOverlays(value);

      // 放大地图，以当前点击的覆盖物为中心放大地图
      this.map.centerAndZoom(point, zoom);

      // 解决清除覆盖物时，百度地图API的JS文件自身报错的问题
      setTimeout(() => {
        // 清除当前覆盖物信息
        this.map.clearOverlays();
      }, 0);
    });

    // 添加覆盖物到地图中
    this.map.addOverlay(label);
  }
  //  createRect() 方法  根据传入的数据创建覆盖物，绑定事件（移动地图，渲染房源列表）
  createRect(point, areaName, count, value) {
    /* 
        1 创建 Label 、设置样式、设置 HTML 内容，绑定单击事件。
        
        2 在单击事件中，获取该小区的房源数据。
        3 展示房源列表。
        4 渲染获取到的房源数据。

        5 调用地图 panBy() 方法，移动地图到中间位置。
          公式：
            垂直位移：(window.innerHeight - 330) / 2 - target.clientY
            水平平移：window.innerWidth / 2 - target.clientX
        6 监听地图 movestart 事件，在地图移动时隐藏房源列表。
      */
    // 创建覆盖物
    let label = new window.BMap.Label("", {
      position: point,
      offset: new window.BMap.Size(-50, -28),
    });
    // 设置内容
    label.setContent(`
      <div class="${styles.rect}">
        <span class="${styles.housename}">${areaName}</span>
        <span class="${styles.housenum}">${count}套</span>
        <i class="${styles.arrow}"></i>
      </div>
      `);
    // 设置样式
    label.setStyle(labelStyle);
    label.id = value;
    label.addEventListener("click", (e) => {
      this.getHouseList(value);
      // console.log(e);
      const { clientX, clientY } = e.changedTouches[0];
      console.log(e, clientX);
      // 租房信息出现后 移动地图到中间位置
      // this.map.panBy( x,y ); // x y为坐标 且为像素值
      this.map.panBy(
        window.innerWidth / 2 - clientX,
        (window.innerHeight - 330) / 2 - clientY
      );
    });
    // 添加到地图中
    this.map.addOverlay(label);
  }
  // 获取小区房源数据
  async getHouseList(id) {
    try {
      //  设置loading效果
      Toast.loading("数据加载中", 0, null, false);
      let res = await API.get("/houses?cityId=" + id);
      console.log(res);
      // 关闭loading效果
      Toast.hide();
      this.setState({
        housesList: res.data.body.list,
        isShowList: true,
      });
    } catch (error) {
      console.log(error);
      // 关闭loading效果
      Toast.hide();
    }
  }

  // 渲染房源列表
  renderHousesList() {
    return this.state.housesList.map((item) => (
      <HouseItem
        key={item.houseCode}
        src={BASE_URL + item.houseImg}
        title={item.title}
        desc={item.desc}
        tags={item.tags}
        price={item.price}
      ></HouseItem>
    ));
  }
  render() {
    return (
      // <div className="map">
      <div className={styles.map}>
        <NavHeader>地图找房</NavHeader>
        {/* 地图容器 */}
        {/* <div id="container">地图组件</div> */}
        <div id="container" className={styles.container}>
          地图组件
        </div>
        {/* 房源列表 */}
        {/* 添加 styles.show 展示房屋列表 */}
        <div
          className={[
            styles.houseList,
            this.state.isShowList ? styles.show : "",
          ].join(" ")}
        >
          <div className={styles.titleWrap}>
            <h1 className={styles.listTitle}>房屋列表</h1>
            <Link className={styles.titleMore} to="/layout/houselist">
              更多房源
            </Link>
          </div>
          <div className={styles.houseItems}>
            {/* 房屋结构 */}
            {this.renderHousesList()}
          </div>
        </div>
      </div>
    );
  }
}
